package june.circlecontroller;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class CircleController extends View{

	private  Context context;
	private  Paint paint;
	private  Handler handler;
	private  Bitmap centerIcon;
	private  RectF CIrect;
	private  PointF cp = new PointF(100, 100);
	private  PointF returnPoint;
	private  float CIX = cp.x;
	private  float CIY = cp.y;
	private  float radian = 50;
	private  boolean isExtends = false;
	
	private  float moveValue;
	private  float moveAngle;
	
	public static final int CIRCLE_CONTROLLER = 1000;
	
	MotionEvent event;
	boolean isRun = false;
	
	public CircleController(Context context) {
		super(context);
		this.context = context;
		init();
	}
	
	
	public CircleController(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
		init();
	}

	private void init(){
		paint = new Paint();
		paint.setStrokeWidth(5);
		paint.setStyle(Style.STROKE);
		paint.setColor(Color.YELLOW);
		
		centerIcon = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
		CIrect = new RectF(CIX, CIY, CIX+centerIcon.getWidth(), CIY+centerIcon.getHeight());
		
	}
	
	/**
	 * 이동값을 전달하기위한 핸들러 셋팅. 파인드 이후 반드시 핸들러를 셋팅해줘야한다.
	 * @param handler
	 */
	public void setControllorHandler(Handler handler){
		this.handler = handler;
	}
	
	/**
	 * 셋팅된 핸들러를 통해 메인 액티비티로 값을 전달한다.
	 * 전달되는 값은 움직일 값, 움직일 각도이다.
	 * @param moveValue
	 * @param moveAngle
	 */
	private void returnValue(float moveValue, float moveAngle, PointF point){
		Message msg = new Message();
		
		//what에는 전달된 위치를. 각각 값에는 무브값과 각도를 전달.
		msg.what = CIRCLE_CONTROLLER;
		msg.arg1 = (int)moveValue;
		msg.arg2 = (int)moveAngle;
		msg.obj  = (Object)point; 
		
		handler.sendMessage(msg);
	}
	/**
	 * 원 밖에서 터치가 이뤄질 경우 그쪽방향으로 포인터를 이동시키기 위한 메소드.
	 * 센터점과 터치점의 각도를 구하고, 센터점에서부터 해당각도로 반지름만큼 이동한
	 * 위치의 좌표값을 반환한다.
	 * @param center 중심점.
	 * @param event 모션이벤트.
	 * @param radian 반지름값. or 지정거리.
	 * @return PointF
	 */
	private PointF circleLimitPoint(PointF center, MotionEvent event){
		
		PointF point = new PointF();
		float angle = getAngle(center, event);
		float radian;
		
		//------반지름 안쪽일때. ------//
		float spacing = spacing(event, cp); 
		if(spacing < this.radian){
			radian = spacing;
		} 
		//반지름 밖이면 반지름값으로 고정.
		else {
			radian = this.radian;
		}
		
		Log.i("june", "spacing : " + spacing);
		
		point.x = (float)(center.x + Math.cos(angle)*radian);
		point.y = (float)(center.y + Math.sin(angle)*radian);
		
		returnPoint = new PointF((float)(Math.cos(angle)*radian), (float)(Math.sin(angle)*radian));
		
		//컨트롤러에서 계산된 값을 핸들러를 통해 전달한다.
//		returnValue(radian, angle, returnPoint);
		
		return point;
	}
	
	private float getAngle(PointF center, MotionEvent event) {
		
		float angle = (float) Math.atan2((event.getX()-center.x), (event.getY()-center.y));
		float angleindegree = (float) (angle * 180 / Math.PI);
		

		return 360 - angle; //???? 뭐여 왜 이놈이 정상이지?
		//북 : 0, 동 : 90, 남 : 180, 서 270.
//		return 180 - angleindegree;
	}
	
	private float spacing(MotionEvent event, PointF center) {
	    float x = center.x - event.getX();
	    float y = center.y - event.getY();
	    return FloatMath.sqrt(x * x + y * y);
	} 
	
	/**
	 * 서클확장 메소드. 외부에서 이 메소드를 실행하면 서클이 확장된다.
	 * 즉, 조작범위가 늘어나면서 그만큼 가속이 가능해진다!
	 */
	public void circleExtands(){
		if(isExtends){
			isExtends = false;
			radian = 50;
		} else {
			isExtends = true;
			radian = 70;	
		}
		
		invalidate();
	}

	
	@Override
	public void draw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.draw(canvas);
		
		//확장모드라면 색상을 레드로 변경.
		if(isExtends){
			paint.setColor(Color.RED);	
		} else {
			paint.setColor(Color.YELLOW);
		}
		
		canvas.drawCircle(cp.x, cp.y, radian, paint);
		
		canvas.drawBitmap(centerIcon, CIX-centerIcon.getWidth()/2, CIY-centerIcon.getHeight()/2, paint);
		
		paint.setColor(Color.BLUE);
		canvas.drawCircle(cp.x, cp.y, 5, paint);
		
		if(isRun){
			//결과값 전송. 스레드건 핸들러건 말썽을 부려서 이런 꼼수를 부려본다.
			returnValue(moveValue, moveAngle, returnPoint);
			invalidate();
		}
	}
	
	@Override
	public boolean onTouchEvent(final MotionEvent event) {
		
		this.event = event;

		if(event.getAction() == MotionEvent.ACTION_DOWN){
			isRun = true;
			
			PointF move = circleLimitPoint(cp, this.event); 
			CIX = move.x;
			CIY = move.y;
		}
		
		if (event.getAction() == MotionEvent.ACTION_MOVE) {
			
			
			PointF move = circleLimitPoint(cp, this.event); 
			CIX = move.x;
			CIY = move.y;
			
		}

		if (event.getAction() == MotionEvent.ACTION_UP) {
			CIX = cp.x;
			CIY = cp.y;
			
			isRun = false;
			
		}
		
		invalidate();
		return true;
	}
	
	
	
	
	
}
